/*
 * Copyright (c) 2017, Li Bo/Alex Lee All rights reserved.
 * 
 * http://www.libo4dream.club/
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
 
package com.hyts.fscan.scanner;


import com.hyts.fscan.base.AbstractFileSystemScanner;
import com.hyts.fscan.config.ScannerConfig;
import com.hyts.fscan.deal.NonRecursiveLoader;
import com.hyts.fscan.deal.RecursiveLoader;
import com.hyts.fscan.domain.Directory;

import java.io.FilenameFilter;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

/**
 * @ClassName: CompositeFScanner
 * @Description: 复杂性操作方法，扫描器服务：利用内部事务fork-join的方法
 * 				 
 * @author: LiBo/Alex Lee
 * @date: 2017年9月30日 下午8:44:48
 * @email: alexlibochn@china-pui.com.cn/alex.link@foxmail.com
 */
public abstract class CompositeFScanner extends AbstractFileSystemScanner {
	
	/**
	 * @fieldName: pool
	 * @fieldType: ForkJoinPool
	 * @Description: forkjoin并行框架
	 */
	private ForkJoinPool pool = new ForkJoinPool(); 
	
	/**
	 * @fieldName: fileList
	 * @fieldType: Queue
	 * @Description: 构建文件列表
	 */
	private List fileList;
	
	/**
	 * @fieldName: directory
	 * @fieldType: Directory
	 * @Description: 本类目录
	 */
	private Directory directory;
	
	
	/**
	 * @Title:CompositeFScanner
	 * 扫描机制:默认非递归
	 * @param path
	 */
	public CompositeFScanner(String path){
		this(path,false);
	}
	
	/**
	 * @Title:CompositeFScanner
	 * @Description:扫描机制
	 * @param path 传入路径
	 * @param isRecursive 是否进行递归
	 */
	public CompositeFScanner(String path,boolean isRecursive){
		directory = new Directory();
		directory.setDirectoryPath(path);
		if(isRecursive)
		{
			RecursiveLoader scan = new RecursiveLoader();
			scan.scanFile(path);
			fileList = scan.getFiles();
		}
		else
		{
			NonRecursiveLoader scan = new NonRecursiveLoader(path);
			scan.scanFiles();
			fileList = scan.getFiles();
		}

	}

	/**
	 * @Title:CompositeFScanner
	 * @Description:扫描机制
	 * @param path 传入路径
	 * @param isRecursive 是否进行递归
	 */
	public CompositeFScanner(String path, FilenameFilter filenameFilter, boolean isRecursive){
		directory = new Directory();
		directory.setDirectoryPath(path);
		if(isRecursive)
		{
			RecursiveLoader scan = new RecursiveLoader(filenameFilter);
			scan.scanFile(path);
			fileList = scan.getFiles();
		}
		else
		{
			NonRecursiveLoader scan = new NonRecursiveLoader(path,filenameFilter);
			scan.scanFiles();
			fileList = scan.getFiles();
		}

	}

	/* (non Javadoc)
	 * @Title: scan
	 * @Description: 扫描方法操作
	 * @param dir
	 * @return
	 * @see com.libo.scan.base.AbstractFileSystemScanner#scan(com.libo.scan.domain.Directory)
	 */
	@Override
	public Integer scan(Directory dir) {
		//校验参数类型
		DoWork work = new DoWork(fileList);
		pool.execute(work);
		try {
			return work.get();
		} catch (InterruptedException | ExecutionException e) {
			e.printStackTrace();
		}finally
		{
			pool.shutdown();
		}
		return 0;
	}
	
	/**
	 * @ClassName: DoWork
	 * @Description: 执行任务工作操作
	 * @author: LiBo/Alex Lee
	 * @date: 2017年9月30日 下午9:30:33
	 * @email: alexlibochn@china-pui.com.cn/alex.link@foxmail.com
	 */
	public class DoWork extends RecursiveTask<Integer>{

		/**
		 * @fieldName: serialVersionUID
		 * @fieldType: long
		 * @Description: 串行化流水号
		 */
		private static final long serialVersionUID = 1L;
		
		/**
		 * @fieldName: innerfileList
		 * @fieldType: List
		 * @Description: TODO
		 */
		private List  innerfileList;
		
		/* (non Javadoc)
		 * @Title: compute
		 * @Description: 执行并行计算操作
		 * @return
		 * @see java.util.concurrent.RecursiveTask#compute()
		 */
		
		@Override
		protected Integer compute() 
		{
			//参数为空
			if(innerfileList == null || innerfileList.isEmpty()) {
				return 0;
			}
			if(innerfileList.size() > ScannerConfig.DEFAULT_FILE_SPLIT_SCANNER_SIZE)
			{
				List splitList = null;
				int splitSegment = innerfileList.size()%
								   ScannerConfig.DEFAULT_FILE_SPLIT_SCANNER_SIZE == 0?
								   innerfileList.size()/(ScannerConfig.
								   DEFAULT_FILE_SPLIT_SCANNER_SIZE):(innerfileList.size()
								   /(ScannerConfig.DEFAULT_FILE_SPLIT_SCANNER_SIZE))+1;
				DoWork[] works = new DoWork[splitSegment];;
				for(int index = 0,index2 = 0; index2<splitSegment && index < innerfileList.size()  ; index2++,index+=ScannerConfig.DEFAULT_FILE_SPLIT_SCANNER_SIZE){
					int start = index2*ScannerConfig.DEFAULT_FILE_SPLIT_SCANNER_SIZE;
					int end = (index2+1)*ScannerConfig.DEFAULT_FILE_SPLIT_SCANNER_SIZE>innerfileList.size()?innerfileList.size():(index2+1)*ScannerConfig.DEFAULT_FILE_SPLIT_SCANNER_SIZE;
					splitList = innerfileList.subList(start,end);
					DoWork work = new DoWork(splitList);
					works[index2] = work;
				}
				invokeAll(works);
			}
			else
			{
				doWork(innerfileList);
			}
			return innerfileList.size();
		}
		/**
		 * @Title:DoWork
		 * 加载列表
		 * @param paramList
		 */
		public DoWork(List paramList) {
			this.innerfileList = paramList;
		}
		
	}
	/**
	 * @Title: doWork
	 * @Description: 制作操作doWork
	 * @return: void
	 */
	public abstract void doWork(List work);
}
